/**
 * @file Promise的扩展
 */
import {isPromise} from "./lib/utils";
import {PromiseExtend} from './lib/interface';
import {Events} from './lib/events';
import { extendPromiseLimit } from './lib/limit';
import { extendsPromiseAllow } from './lib/allow';
import { extendsPromiseShake } from './lib/shake';
import { extendPromiseCache } from './lib/cache';
import { extendPromiseManager } from './lib/manager';

export const PromiseExtends: PromiseExtend.Result = (function() {
    /**
     * static function
     */

    /**
     *  统一捕捉异常
     *  @deprecated
     */
    const extendsPromiseCatch = () => {
        // @ts-ignore
        Promise.catch = function (
            type: PromiseExtend.PromiseCatch.CatchType,
            data: PromiseExtend.PromiseCatch.data
        ) {
            const {key, error, errorFn, stopBubbling} = data;
          switch (type) {
              case PromiseExtend.PromiseCatch.CatchType.LISTEN:
                  return Events.listen(key, errorFn);
              case PromiseExtend.PromiseCatch.CatchType.PUBLISH:
                  return Events.publish(key, error, stopBubbling);
              case PromiseExtend.PromiseCatch.CatchType.CLEAN:
                  return Events.clean(key);
              default:
                  return;
          }
        }
    };

    /**
     * 实例方法
     */
    const extendsPromiseDone = () => {
        // @ts-ignore
        if (typeof Promise.prototype.done === 'function') {
            return null;
        }
        // @ts-ignore
        Promise.prototype.done = function(onFulfilled, onRejected) {
            this.then(onFulfilled, onRejected)
                .catch(error => {
                    setTimeout(() => {
                        throw error;
                    }, 0);
                });
        }
    };

    const reset = () => {
        // @ts-ignore
        Promise.limit = undefined;
        // @ts-ignore
        Promise.shake = undefined;
        // @ts-ignore
        Promise.allow = undefined;
        // @ts-ignore
        // Promise.catch = undefined;
        // @ts-ignore
        Promise.cache = undefined;
        // @ts-ignore
        Promise.clearCache = undefined;
        // @ts-ignore
        Promise.manager = undefined;
    };

    return {
        extend(options: PromiseExtend.Options) {
            const {isExtend = true} = options;
            if (!isPromise() || !isExtend) {
                reset();
                return false;
            }
            extendPromiseLimit();
            extendsPromiseShake();
            // extendsPromiseCatch();
            extendsPromiseDone();
            extendsPromiseAllow();
            extendPromiseCache();
            extendPromiseManager();
            return true;
        }
    }
})();